package br.com.it4.zmed.persistence;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import br.com.it4.framework.persistence.dao.BaseDAOImpl;
import br.com.it4.framework.persistence.exception.PersistenceException;
import br.com.it4.zmed.entity.Atendimento;
import br.com.it4.zmed.filter.AtendimentoFilter;

/**
 * Repositório para persistência básica para o atendimento.
 * 
 * @author Mozart Silva (mozart.vsilva@gmail.com)
 * 
 */
@Repository(value = "atendimentoRepository")
public class AtendimentoDAOImpl extends BaseDAOImpl<Atendimento> implements AtendimentoDAO {

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public List<Atendimento> get(AtendimentoFilter filtro) throws PersistenceException {
        List<Atendimento> atendimentos = null;
        try {
            Query query = this.getQuery(filtro, false);
            atendimentos = (List<Atendimento>) query.getResultList();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
        return atendimentos;
    }

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public List<Atendimento> get(AtendimentoFilter filtro, int registroInicio, int registroFim)
            throws PersistenceException {
        List<Atendimento> atendimentos = null;
        try {
            Query query = this.getQuery(filtro, false);
            query.setFirstResult(registroInicio);
            query.setMaxResults(registroFim);
            atendimentos = (List<Atendimento>) query.getResultList();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }
        return atendimentos;
    }

    /** {@inheritDoc} */
    public Long getCount(AtendimentoFilter filtro) throws PersistenceException {
        Long count = null;

        try {
            Query query = this.getQuery(filtro, true);
            count = (Long) query.getSingleResult();
        } catch (Exception e) {
            throw new PersistenceException(e);
        }

        return count;
    }

    /**
     * Monta query de consulta de atendimento.
     * 
     * @param filtro
     *            Filtro para montagem da query.
     * @param isCount
     *            true se é um count da consulta e false caso seja um consulta
     *            dos dados.
     * @return A Query montada.
     */
    private Query getQuery(AtendimentoFilter filtro, boolean isCount) {
        EntityManager entityManager = this.getEntityManager();

        StringBuffer jpql = new StringBuffer();
        if (!isCount) {
            jpql.append("select atendimento from Atendimento atendimento ");
        } else {
            jpql.append("select count(atendimento) from Atendimento atendimento ");
        }

        jpql.append("where 1 = 1 ");

        if (filtro.getPaciente() != null && filtro.getPaciente().getNome() != null
                && !filtro.getPaciente().getNome().isEmpty()) {
            jpql.append("and upper(atendimento.paciente.nome) like upper(:nomePaciente) ");
        }

        if (filtro.getMedicoRequisitante() != null && filtro.getMedicoRequisitante().getNome() != null
                && !filtro.getMedicoRequisitante().getNome().isEmpty()) {
            jpql.append("and upper(atendimento.medicoRequisitante.nome) like upper(:nomeMedicoRequisitante) ");
        }

        if (filtro.getData() != null) {
            jpql.append("and atendimento.data = :dataAtendimento ");
        }

        if (filtro.getConvenio() != null && filtro.getConvenio().getCodigo() != null
                && filtro.getConvenio().getCodigo() != 0) {
            jpql.append("and atendimento.convenio.codigo = :codigoConvenio ");
        }

        if (filtro.getExame() != null && filtro.getExame().getCodigo() != null
                && !filtro.getExame().getCodigo().isEmpty()) {
            jpql.append("and atendimento.convenio.codigo = :codigoExame ");
        }

        if (!isCount) {
            jpql.append("order by upper(atendimento.paciente.nome)");
        }

        Query query = entityManager.createQuery(jpql.toString());

        if (filtro.getPaciente() != null && filtro.getPaciente().getNome() != null
                && !filtro.getPaciente().getNome().isEmpty()) {
            query.setParameter("nomePaciente", "%" + filtro.getPaciente().getNome() + "%");
        }

        if (filtro.getData() != null) {
            query.setParameter("dataAtendimento", filtro.getData());
        }

        if (filtro.getMedicoRequisitante() != null && filtro.getMedicoRequisitante().getNome() != null
                && !filtro.getMedicoRequisitante().getNome().isEmpty()) {
            query.setParameter("nomeMedicoRequisitante", "%" + filtro.getMedicoRequisitante().getNome() + "%");
        }

        if (filtro.getConvenio() != null && filtro.getConvenio().getCodigo() != null
                && filtro.getConvenio().getCodigo() != 0) {
            query.setParameter("codigoConvenio", filtro.getConvenio().getCodigo());
        }

        if (filtro.getExame() != null && filtro.getExame().getCodigo() != null
                && !filtro.getExame().getCodigo().isEmpty()) {
            query.setParameter("codigoExame", filtro.getExame().getCodigo());
        }

        return query;
    }
}